﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Web;
using SaleDiscount.Data.CollectionClasses;
using SaleDiscount.Data.EntityClasses;
using SaleDiscount.Data.HelperClasses;
using SaleDiscount.Portal.Service;
using eBay.Service.Call;
using eBay.Service.Core.Sdk;
using eBay.Service.Core.Soap;

namespace SaleDiscount.Portal.eBay
{

    public class eBaySession
    {
        public ApiContext ApiContext
        {
            get
            {
                if (HttpContext.Current.Session["CurrentUser"] == null || string.IsNullOrWhiteSpace(HttpContext.Current.Session["CurrentUser"].ToString()))
                {
                    throw new Exception("Session is timeout.");
                }
                return ApiContexts[HttpContext.Current.Session["CurrentUser"].ToString()];

            }
        }
        private static readonly object syncRoot = new object();
        public eBaySession()
        {
        }
        static eBaySession()
        {
            ApiContexts = new Dictionary<string, ApiContext>();
        }


        public static IDictionary<string, ApiContext> ApiContexts { get; set; }
        public static ApiContext LoadApiContext(string token, string ebayUser)
        {
            if (!ApiContexts.ContainsKey(ebayUser))
            {
                lock (syncRoot)
                {
                    if (!ApiContexts.ContainsKey(ebayUser))
                        ApiContexts.Add(ebayUser, ApiContextLoader.LoadApiContext(token, ebayUser));


                }
            }
            return ApiContexts[ebayUser];
        }

        public static void Clear(string ebayUser)
        {

        }

        public static ApiContext LoadEmptyApiContext(string ebayUserId)
        {
            ApiContext context = ApiContextLoader.LoadApiContext(string.Empty, ebayUserId)
                ;
            return context;
        }


        public static EbayUserTokenEntity ActivateUser(ApiContext context, string sessionId, string ebayUserId, int? id)
        {
            string token = string.Empty;
            var transaction = new Transaction(IsolationLevel.ReadCommitted, "Activate User");
            try
            {
                context.ApiCredential.eBayAccount = null;
                var fetchTokenCall = new FetchTokenCall(context);
                token = fetchTokenCall.FetchToken(sessionId);

                var ebaydbUserEntity = new EbayUserTokenEntity();
                if (id.HasValue)
                {
                    ebaydbUserEntity = new EbayUserTokenEntity(id.Value);
                    ebaydbUserEntity.Token = string.Empty;
                }
                if (!string.IsNullOrEmpty(token))
                {
                    context.ApiCredential.eBayToken = token;

                    ebaydbUserEntity.Token = token;
                    ebaydbUserEntity.EBayUserId = ebayUserId;
                    ebaydbUserEntity.CreatedDate = ebaydbUserEntity.UpdatedDate = DateTime.Now;
                    //get token status
                    var getTokenStatusCall = new GetTokenStatusCall(context);
                    TokenStatusType tokenStatus = getTokenStatusCall.GetTokenStatus();
                    if (tokenStatus.Status == TokenStatusCodeType.Active)
                        ebaydbUserEntity.IsActive = true;
                    else
                        ebaydbUserEntity.IsActive = false;
                    ebaydbUserEntity.TokenExpirationDate = tokenStatus.ExpirationTime;
                    transaction.Add(ebaydbUserEntity);

                    ebaydbUserEntity.Save();

                    transaction.Commit();

                }
                return ebaydbUserEntity;
            }
            catch (Exception)
            {
                transaction.Rollback();
                throw;
            }
        }

        public static string GetSessionId(ApiContext context, string ruName)
        {
            return new GetSessionIDCall(context).GetSessionID(ruName);
        }
        public StoreCustomCategoryTypeCollection GeteBayStoreCategories()
        {
            var store = new GetStoreCall(ApiContext).GetStore();
            if (store == null) return null;
            return store.CustomCategories;
        }


        public ItemTypeCollection CallGetSellerList(DateTime endDateTimeFrom, DateTime endDateTimeTo)
        {
            try
            {
                var api = new GetSellerListCall(ApiContext);
                //api.IncludeWatchCount = true;
                api.DetailLevelList.Add(DetailLevelCodeType.ReturnAll);
                api.EndTimeFilter = new TimeFilter(endDateTimeFrom, endDateTimeTo);

                var pagination = new PaginationType();
                pagination.EntriesPerPage = 100;
                api.Pagination = pagination;

                int pageNum = 1;
                bool hasMore = true;
                var itemCollection = new ItemTypeCollection();
                while (hasMore)
                {
                    pagination.PageNumber = pageNum++;
                    itemCollection.AddRange(api.GetSellerList());
                    hasMore = api.ApiResponse.HasMoreItems;
                }
                return itemCollection;
            }
            catch (Exception)
            {
                throw;
            }
        }

        public PromotionalSaleStatusCodeType SetPromotionalSale(ModifyActionCodeType action, PromotionalSaleType promationSale)
        {
            var api = new SetPromotionalSaleCall(ApiContext);
            api.SetPromotionalSale(action, promationSale);
            promationSale.PromotionalSaleID = api.PromotionalSaleID;
            return api.Status;
        }

        public PromotionalSaleStatusCodeType SetPromotionalSaleListings(long promotionalSaleID, ModifyActionCodeType action, ItemIDArrayType promotionalSaleItemIDArrayList, long storeCategoryID, long categoryID, bool allFixedPriceItems, bool allStoreInventoryItems, bool allAuctionItems)
        {
            var api = new SetPromotionalSaleListingsCall(ApiContext);
            api.PromotionalSaleID = promotionalSaleID;
            api.Action = action;
            if (promotionalSaleItemIDArrayList.ItemID.Count > 0)
                api.PromotionalSaleItemIDArrayList = promotionalSaleItemIDArrayList;
            if (storeCategoryID > 0 && allStoreInventoryItems)
                api.StoreCategoryID = storeCategoryID;
            if (categoryID > 0)
                api.CategoryID = categoryID;

            api.AllFixedPriceItems = allFixedPriceItems;
            api.AllStoreInventoryItems = allStoreInventoryItems;
            api.AllAuctionItems = allAuctionItems;
            api.Execute();
            return api.Status;
        }

        public PromotionalSaleStatusCodeType RemovePromotionalSaleListings(long promotionalSaleId,ItemIDArrayType removedPromotionalSaleItemIdArrayList)
        {
            var api = new SetPromotionalSaleListingsCall(ApiContext);
            api.PromotionalSaleID = promotionalSaleId;
            api.Action = ModifyActionCodeType.Delete;
            if (removedPromotionalSaleItemIdArrayList.ItemID.Count > 0)
                api.PromotionalSaleItemIDArrayList = removedPromotionalSaleItemIdArrayList;
            api.Execute();
            return api.Status;
        }


        public ItemTypeCollection GetActiveListings(ListingTypeCodeType listingTypeCodeType, ItemSortTypeCodeType sort)
        {
            try
            {
                var api = new GetMyeBaySellingCall(ApiContext);
                //api.IncludeWatchCount = true;
                api.DetailLevelList.Add(DetailLevelCodeType.ReturnAll);
                api.ActiveList =new ItemListCustomizationType();
                api.ActiveList.Include = true;
                api.ActiveList.ListingType = listingTypeCodeType;
                api.ActiveList.Sort = sort;
                var pagination = new PaginationType();
                pagination.EntriesPerPage = 100;
                api.ActiveList.Pagination = pagination;

                int pageNum = 1;
                bool hasMore = true;
                var itemCollection = new ItemTypeCollection();
                while (hasMore)
                {
                    pagination.PageNumber = pageNum++;
                    api.Execute();
                    itemCollection.AddRange(api.ActiveListReturn.ItemArray);
                    hasMore = api.ActiveListReturn.ItemArray.Count == 100;
                }
                return itemCollection;
            }
            catch (Exception)
            {
                throw;
            }
        }
        protected bool CheckForErrors(string function, ApiCall call, out string errorMessage)
        {
            // Warning out to not get Schema Out Of Date messages
            errorMessage = string.Empty;
            if (call.HasError /*|| call.HasWarning */)
            {
                ApiException exc = call.ApiException;
                Debug.Assert(exc != null);
                var sb = new StringBuilder(function);
                sb.Append(":\n");
                ProcessApiException(exc, sb);

                errorMessage = sb.ToString();
                ShowMessage(errorMessage);
            }


            return !call.HasError;
        }

        protected void ShowException(string function, Exception e, out string errorMessage)
        {
            var sbInfo = new StringBuilder();
            if (e is ApiException)
            {
                var exc = e as ApiException;
                ProcessApiException(exc, sbInfo);
            }

            var sb = new StringBuilder();
            sb.AppendFormat("{0}: caught {1}\n", function,
                            e.GetType());
            if (sbInfo.Length > 0)
                sb.AppendFormat("Info: {0}", sbInfo);
            /*
            if (e.InnerException != null)
                sb.AppendFormat("InnerException: {0}",
                    e.InnerException.ToString());
            */

            errorMessage = sbInfo.ToString();
            ShowMessage(sb.ToString());
        }

        private void ProcessApiException(ApiException exc, StringBuilder sbInfo)
        {
            foreach (ErrorType err in exc.Errors)
            {
                if (err.ErrorCode == "488") //UUID error
                {
                    int index = err.LongMessage.LastIndexOf("，");
                    if (index < 0)
                    {
                        index = err.LongMessage.LastIndexOf(",");
                    }
                    err.LongMessage =
                        err.ShortMessage =
                        "This item has already been uploaded," + err.LongMessage.Substring(index + 1);
                }
                sbInfo.AppendFormat("{0}\n", err.LongMessage);
            }
        }


        public void ShowMessage(string msg)
        {
            Log(msg);
        }

        protected void Log(string msg)
        {
            ApiContext.ApiLogManager.RecordMessage(msg);
        }

    }
}